#include "StdAfx.h"
#include "SingleThread.h"
#include <process.h>


CSingleThread::CSingleThread(void):
m_hStartEvent(NULL),
m_hThread(NULL),
m_dwThreadID(0),
m_bAbort(FALSE)
{
}

CSingleThread::~CSingleThread(void)
{
	DestroyThread();
}

BOOL CSingleThread::Create(BOOL bTerminateIfExists)
{
	if(bTerminateIfExists == TRUE)
	{
		DestroyThread();
	}

	m_hStartEvent = CreateEvent(NULL,TRUE,FALSE,L"SingleThreadStartEvent");
	m_hThread = (HANDLE)_beginthreadex(NULL,0,ThreadProc,this,0,(unsigned int*)&m_dwThreadID);
	if(m_hThread && m_hStartEvent)
	{
		WaitForSingleObject(m_hStartEvent,INFINITE);
		::CloseHandle(m_hStartEvent);
		m_hStartEvent = NULL;
	}

	return TRUE;
}

void CSingleThread::DestroyThread()
{
	m_bAbort = TRUE;

	if(m_hThread != NULL && IfActive() == TRUE)
	{
		if(GetCurrentThreadId() == m_dwThreadID)
			return ;
		PostMessage(WM_QUIT,0,0);
		MSG msg;
		for(;;)
		{
			DWORD dwCode = MsgWaitForMultipleObjects(1,&m_hThread,FALSE,INFINITE,QS_ALLINPUT);
			if(dwCode == WAIT_OBJECT_0 || dwCode == WAIT_FAILED)
				break;
			if(dwCode == WAIT_OBJECT_0 + 1)
			{
				if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
				{
					::TranslateMessage(&msg);
					::DispatchMessage(&msg);
				}
			}
		}
		::CloseHandle(m_hThread);
		m_hThread = NULL;
	}
}

BOOL CSingleThread::PostMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
	if(m_hThread && m_dwThreadID)
	{
		if(!PostThreadMessage(m_dwThreadID,msg,wParam,lParam))
			return FALSE;
		else
			return TRUE;
	}
	return FALSE;
}

BOOL CSingleThread::IfActive()
{
	if(m_hThread == NULL)
		return FALSE;
	if(WaitForSingleObject(m_hThread,1) == WAIT_TIMEOUT)
		return TRUE;
	return FALSE;
}

BOOL CSingleThread::IfAbort()
{
	return m_bAbort;
}

UINT __stdcall CSingleThread::ThreadProc(LPVOID lpParam)
{
	CSingleThread* pThis = (CSingleThread*)lpParam;
	if(pThis)
	{
		SetEvent(pThis->m_hStartEvent);
		pThis->DefThreadProc();
	}
	return 0;
}

UINT __stdcall CSingleThread::DefThreadProc()
{
	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0 ))
	{
		::TranslateMessage(&msg); 
		::DispatchMessage(&msg);
	}
	return 0;
}
